package com.ctshk.sapp.scenic.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ctshk.common.annotations.OperationLogAnnotation;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.OperationLogModel;
import com.ctshk.common.enums.OperationLogType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.web.support.BaseController;
import com.ctshk.rpc.scenic.dto.TicketLuckSaveDTO;
import com.ctshk.rpc.scenic.dto.TicketTypeLuckDrawDTO;
import com.ctshk.rpc.scenic.dto.TicketTypeLuckDrawNumDTO;
import com.ctshk.rpc.scenic.req.CheckDuplicateReq;
import com.ctshk.rpc.scenic.req.TicketLuckDrawApplyUserInfoReq;
import com.ctshk.rpc.scenic.req.TicketTypeLuckDrawCacheReq;
import com.ctshk.rpc.scenic.req.TicketTypeLuckDrawReq;
import com.ctshk.rpc.scenic.service.ITicketTypeLuckDrawService;
import com.ctshk.sapp.scenic.convert.LocalDateConverter;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 门票抽奖种类表 前端控制器
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-02-18
 */
@Api(value = "冬奥会场次相关接口", tags = "冬奥会")
@RestController
@RequestMapping("/ticket-type-luck-draw")
public class TicketTypeLuckDrawController extends BaseController {

    @DubboReference
    private ITicketTypeLuckDrawService drawService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 文件上传
     * 根据excel表格插入数据，获取用户上传的excel文件，读取数据
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) throws IOException {
        byte[] pic = file.getBytes();
        drawService.upload(pic);
        return "success";
    }

    /**
     * 下载导出
     */
    @GetMapping("/download")
    public void download(HttpServletResponse response) throws IOException {
        System.out.println("download");
        List<TicketTypeLuckDrawDTO> scenicResourceTicketList = drawService.selectTicketTypeLuckDrawList();
        System.out.println("service download");
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = null;
        try {
            fileName = URLEncoder.encode("测试", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), TicketTypeLuckDrawDTO.class).sheet("模板").registerConverter(new LocalDateConverter()).doWrite(scenicResourceTicketList);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @ApiOperation("所有门票信息(分页)")
    @PostMapping("/list")
    public Result<PageResponse<TicketTypeLuckDrawDTO>> listAll() {
        return Result.success(drawService.listAll());
    }

    @ApiOperation("自定义（场次，赛区，级别，日期）查询")
    @PostMapping("/queryCondition")
    public Result<PageResponse<TicketTypeLuckDrawDTO>> queryCondition(
            @RequestBody TicketTypeLuckDrawReq ticket) {
        return drawService.queryCondition(ticket);
    }

    /**
     * 缓存场次票数
     *
     * @param req
     * @return
     */
    @ApiOperation(value = "缓存场次票数", notes = "缓存场次票数")
    @PostMapping("/cacheSessions")
    public Result cacheSessions(@Valid @RequestBody TicketTypeLuckDrawCacheReq req) {
        try {
            String key = "ticketTypeLuckDrawCache" + req.getUuid();
            Map<String, Integer> map = new HashMap<>();
            Object sessionMap = redisTemplate.opsForValue().get(key);
            if (sessionMap == null) {
                map.put(req.getId().toString(), req.getNumber());
            } else {
                map = (Map<String, Integer>) sessionMap;
                if (req.getNumber() == 0) {
                    map.remove(req.getId());
                }else {
                    map.put(req.getId().toString(), req.getNumber());
                }
            }
            redisTemplate.opsForValue().set(key, map, 24, TimeUnit.HOURS);
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed(SystemError.SYS_500);
        }

    }

    /**
     * 校验购票上限
     * @return
     */
    @ApiOperation(value = "校验购票上限", notes = "校验购票上限")
    @GetMapping("/checkCacheSession/{uuid}")
    public Result checkCacheSession(@PathVariable String uuid) {
        return drawService.checkCacheSession(uuid);
    }

    /**
     * 删除缓存
     * @return
     */
    @ApiOperation(value = "删除缓存场次票数", notes = "删除缓存场次票数")
    @DeleteMapping("/delCacheSession/{uuid}")
    public Result delCacheSession(@PathVariable String uuid) {
        try {
            String key = "ticketTypeLuckDrawCache" + uuid;
            Boolean ret = redisTemplate.delete(key);
            return Result.success(ret != null && ret);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed(SystemError.SYS_500);
        }
    }

    /**
     * 删除单个场次缓存
     * @return
     */
    @ApiOperation(value = "删除单个场次缓存", notes = "删除单个场次缓存")
    @DeleteMapping("/delOneCache/{uuid}/{id}")
    public Result delOneCache(@PathVariable String uuid, @PathVariable Long id) {
        try {
            String key = "ticketTypeLuckDrawCache" + uuid;
            Object o = redisTemplate.opsForValue().get(key);
            if (null != o) {
                Map<String, Integer> map = (Map<String, Integer>) o;
                map.remove(String.valueOf(id));
                redisTemplate.opsForValue().set(key, map, 24, TimeUnit.HOURS);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed(SystemError.SYS_500);
        }
        return Result.success();
    }

    /**
     * 获取缓存场次票数
     *
     * @param uuid
     * @return
     */
    @ApiOperation(value = "获取缓存场次票数", notes = "获取缓存场次票数")
    @GetMapping("/getCacheSessions/{uuid}")
    public Result<List<TicketTypeLuckDrawDTO>> getCacheSessions(@PathVariable String uuid) {
        try {
            String key = "ticketTypeLuckDrawCache" + uuid;
            redisTemplate.opsForValue().get(key);
            Object o = redisTemplate.opsForValue().get(key);
            if (null != o) {
                Map<String, Integer> map = (Map<String, Integer>) o;
                List<String> ids = new ArrayList<>(map.keySet());
                List<TicketTypeLuckDrawDTO> ticketTypeLuckDrawDTOS = new ArrayList<>();
                if (CollectionUtils.isEmpty(ids)) {
                    return Result.success(ticketTypeLuckDrawDTOS);
                }
                ticketTypeLuckDrawDTOS = drawService.queryTicketTypeLuckDrawByIds(ids);
                ticketTypeLuckDrawDTOS.forEach(dto -> {
                    ids.forEach(id -> {
                        if (dto.getId().toString().equals(id)) {
                            dto.setCacheNumber(map.get(id));
                        }
                    });
                });
                return Result.success(ticketTypeLuckDrawDTOS);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed(SystemError.SYS_500);
        }
        return Result.success(null);
    }

    /**
     * 点击立即报名->保存三张表
     * 以及查询出queryNumber 和 门票类型和其数量（根据queryNumber）
     *
     * @param userInfoReq
     * @return
     */
    @ApiOperation("勾选门票和申请人资料的添加")
    @PostMapping("/saveTicket")
    public Result<TicketLuckSaveDTO> saveTicket(@Valid @RequestBody TicketLuckDrawApplyUserInfoReq userInfoReq) {
        //最多只能添加四个种类的门票
        if (userInfoReq.getTickets().size() > 4) {
            return Result.failed(SystemError.SEASON_TICKET_20026);
        }
        return drawService.saveTicket(userInfoReq);
    }

    /**
     * 校验是否重复
     * @param checkDuplicateReq
     * @return
     */
    @ApiOperation(value = "校验是否重复", notes = "校验是否重复")
    @OperationLogAnnotation(operModul = OperationLogModel.TICKET, operType = OperationLogType.QUERY, operTitle = "校验是否重复", operDesc = "校验是否重复")
    @PostMapping("/check-duplicate")
    public Result checkDuplicate(@Valid @RequestBody CheckDuplicateReq checkDuplicateReq) {
        return drawService.checkDuplicate(checkDuplicateReq);
    }

    /**
     * 报名成功之后
     * 根据查询编号查询：门票 和 门票数量
     *
     * @param queryNumber
     */
    @ApiOperation(value = "根据查询编号查询：门票 和 门票数量", notes = "根据查询编号查询：门票 和 门票数量")
    @GetMapping("/selectTicketByQueryNumber/{queryNumber}")
    public Result<List<TicketTypeLuckDrawNumDTO>> selectTicketByQueryNumber(@PathVariable String queryNumber) {
        return Result.success(drawService.selectTicketByQueryNumber(queryNumber));

    }


}
